#ifndef __M_CONSUMER_H__
#define __M_CONSUMER_H__

#include "../MQcommon/helper.hpp"
#include "../MQcommon/mq_msg.pb.h"
#include"../MQcommon/logger.hpp"

#include <google/protobuf/map.h>
#include <iostream>
#include <unordered_map>
#include <mutex>
#include <memory>

namespace bitmq{
    using ConsumerCallback = std::function<void(const std::string&, const BasicProperties *, const std::string&)>;
    struct Consumer {
        using ptr=std::shared_ptr<Consumer>;
        std::string tag;//消费者标识
        std::string qname;//消费者所在队列标识
        bool auto_ack;//是否自动应答
        ConsumerCallback callback;//消费者的回调函数

        Consumer(){
            DLOG("调用Consumer的析构函数");
            DLOG("new Consumer: %p", this);
        }
        Consumer(const std::string &ctag, const std::string &queue_name,  bool ack_flag, const ConsumerCallback &cb):
            tag(ctag), qname(queue_name), auto_ack(ack_flag), callback(std::move(cb)) {
            DLOG("new Consumer: %p", this);
        }
        ~Consumer() {
            DLOG("del Consumer: %p", this);
        }
    };

    class QueueConsumer{
        public:
        using ptr=std::shared_ptr<QueueConsumer>;
        QueueConsumer(const std::string& qname):_qname(qname),_rr_seq(0){}
        Consumer::ptr createConsumer(const std::string &ctag, const std::string &queue_name,  bool ack_flag, const ConsumerCallback &cb){
            std::unique_lock<std::mutex> _mutex;
            //优先判断消费者是否已经存在
            for (auto it = _consumers.begin(); it != _consumers.end(); ++it) {
                if ((*it)->tag == ctag) {
                    DLOG("在队列[%s]中已经存在消费者[%s]！",_qname,ctag);
                    return (*it);
                }
            }
            auto it = std::make_shared<Consumer>(ctag,queue_name,ack_flag,cb);
            _consumers.push_back(it);
            return it;
        }
        //删除队列的一个消费者
        void remove(const std::string &ctag){
            std::unique_lock<std::mutex> _mutex;
            //先判断消费者是否已经在队列当中存在 
            for (auto it = _consumers.begin(); it != _consumers.end(); ++it) {
                if ((*it)->tag == ctag) {
                    _consumers.erase(it);
                    DLOG("在队列[%s]中删除消费者[%s]成功！",_qname.c_str(),ctag.c_str());
                    return ;
                }
            }
            DLOG("队列[%s]中要删除的消费者[%s]不存在！",_qname,ctag);
            return;
            
        }
        //队列获取消费者：RR轮转获取
        Consumer::ptr choose(){
            std::unique_lock<std::mutex> lock(_mutex);
            if(_consumers.empty()){
                DLOG("队列[%s]当中没有消费者订阅！",_qname.c_str());
                return nullptr;
            }
            int pos = _rr_seq % _consumers.size();
            _rr_seq++;
            return _consumers[pos];
        }
        //是否为空
        bool empty(){
            std::unique_lock<std::mutex> _mutex;
            return _consumers.empty();
        }
        //判断指定消费者是否存在
        bool exists(const std::string &ctag){
            //优先判断消费者是否已经存在
            for (auto it = _consumers.begin(); it != _consumers.end(); ++it) {
                if ((*it)->tag == ctag) {
                    DLOG("在队列[%s]中已经存在消费者[%s]！",_qname,ctag);
                    return true;
                }
            }
            return false;
        }
        //清理所有消费者
        void clear(){
            std::unique_lock<std::mutex> _mutex;
            _rr_seq=0;
            _consumers.clear();
        } 
        private:
        std::mutex _mutex;
        std::string _qname;
        uint64_t _rr_seq;//轮转序号
        std::vector<Consumer::ptr> _consumers;
    };

class ConsumerManager {
        public:
        using ptr = std::shared_ptr<ConsumerManager>;
        ConsumerManager(){}
        void initQueueConsumer(const std::string &qname){
            {
                std::unique_lock<std::mutex> lock(_mutex);
                auto it = _qconsumers.find(qname);
                if(it != _qconsumers.end()){
                    DLOG("队列[%s]消费者管理句柄已经存在，不可重复创建！");
                    return ;
                }
            }
            auto qc_ptr = std::make_shared<QueueConsumer>(qname);
            _qconsumers.insert(std::make_pair(qname,qc_ptr));
        }
        void destroyQueueConsumer(const std::string &qname){
            {
                std::unique_lock<std::mutex> lock(_mutex);
                auto it = _qconsumers.find(qname);
                if(it == _qconsumers.end()){
                    DLOG("队列[%s]消费者管理句柄不存在，不可删除！");
                    return ;
                }
            }
            _qconsumers.erase(qname);
        }
        void removeConsumer(const std::string &ctag, const std::string &qname){
            QueueConsumer::ptr qc_ptr;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                auto it = _qconsumers.find(qname);
                if(it == _qconsumers.end()){
                    DLOG("队列[%s]消费者管理句柄不存在，不可删除！");
                    return ;
                }
                qc_ptr = it->second;
            }
            qc_ptr->remove(ctag);
        }
        
        Consumer::ptr chooseConsumer(const std::string &qname){
            QueueConsumer::ptr qc_ptr;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                auto it = _qconsumers.find(qname);
                if(it == _qconsumers.end()){
                    DLOG("队列[%s]消费者管理句柄不存在，无法选中！");
                    return Consumer::ptr();
                }
                qc_ptr = it->second;
            }
            return qc_ptr->choose();
        }
        //查看目标队列的消费者是否为空
        bool queueConsumerEmpty(const std::string &qname){
            QueueConsumer::ptr qc_ptr;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                auto it = _qconsumers.find(qname);
                if(it == _qconsumers.end()){
                    DLOG("队列[%s]消费者管理句柄不存在，无法选中！");
                    return false;
                }
                qc_ptr = it->second;
            }
            return qc_ptr->empty();
            
        }
        bool exists(const std::string &ctag, const std::string &qname){
            QueueConsumer::ptr qc_ptr;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                auto it = _qconsumers.find(qname);
                if(it == _qconsumers.end()){
                    DLOG("队列[%s]消费者管理句柄不存在，无法选中！");
                    return false;
                }
                qc_ptr = it->second;
            }
            return qc_ptr->exists(ctag);
        }
        Consumer::ptr createConsumer(const std::string &ctag, const std::string &queue_name,  bool ack_flag, const ConsumerCallback &cb) {
            //获取队列的消费者管理单元句柄，通过句柄完成新建
            QueueConsumer::ptr qcp;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                auto it = _qconsumers.find(queue_name);
                if (it == _qconsumers.end()) {
                    DLOG("没有找到队列 %s 的消费者管理句柄！", queue_name.c_str());
                    return Consumer::ptr();
                }
                qcp = it->second;
            }
            return qcp->createConsumer(ctag, queue_name, ack_flag, cb);
        }
        void clear() {
            std::unique_lock<std::mutex> lock(_mutex);
            _qconsumers.clear();
        }
        private:
        std::mutex _mutex;
        std::unordered_map<std::string, QueueConsumer::ptr> _qconsumers;
    };
}
#endif